/**
 * Copyright 2008 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package kiff.entity;

import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import kiff.security.Acl;
import kiff.security.AclEntry;
import kiff.security.Permission;
import kiff.security.Principal;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * Forum Access Control List Entry.
 * @author Adam
 * @version $Id: ForumAclEntry.java 59 2008-10-22 05:52:05Z a.ruggles $
 */
@Entity @Table(name = "forum_acl_entries")
@org.hibernate.annotations.Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ForumAclEntry implements AclEntry, CoreEntity<Integer> {
    /**
	 * Serial Version UID.
	 */
	private static final long serialVersionUID = 5023633780533081749L;

	/**
	 * The Acl that this entry belongs to.
	 */
	private Acl acl;

	/**
	 * The unique identifier.
	 */
	private Integer id;

	/**
	 * The permission for the entry.
	 */
	private Permission permission;

	/**
	 * The principal for the entry.
	 */
	private Principal principal;

	/**
	 * Default Constructor.
	 */
	public ForumAclEntry() { }

	/**
	 * Constructor that sets the principal and permission.
	 * @param acl The ACL to assign the constructed entry to.
	 * @param principal The principal of the ACL Entry to construct.
	 * @param permission The permissions of the ACL Entry to construct.
	 */
	public ForumAclEntry(final Acl acl, final Principal principal, final Permission permission) {
		this.acl = acl;
		this.principal = principal;
		this.permission = permission;
	}

	/**
	 * Constructor that sets the principal and permission.
	 * @param principal The principal of the ACL Entry to construct.
	 * @param permission The permissions of the ACL Entry to construct.
	 */
	public ForumAclEntry(final Principal principal, final Permission permission) {
		this.principal = principal;
		this.permission = permission;
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (!(obj instanceof ForumAclEntry)) {
			return false;
		}
		ForumAclEntry rhs = (ForumAclEntry) obj;
		return new EqualsBuilder()
			.append(permission, rhs.getPermission())
			.append(principal, rhs.getPrincipal())
			.isEquals();
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.security.AclEntry#getAcl()
	 */
	@ManyToOne(targetEntity = ForumAcl.class, fetch = FetchType.LAZY)
	public Acl getAcl() {
		return acl;
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.entity.CoreEntity#getId()
	 */
	@Id @GeneratedValue(strategy = GenerationType.AUTO)
	public Integer getId() {
		return id;
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.security.AclEntry#getPermission()
	 */
	@Embedded @org.hibernate.annotations.Target(ForumPermission.class)
	public Permission getPermission() {
		return permission;
	}

	/**
	 * @see kiff.security.AclEntry#getPrincipal()
	 */
	@ManyToOne(targetEntity = Role.class, fetch = FetchType.LAZY)
	public Principal getPrincipal() {
		return principal;
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder(5, 11)
			.append(permission)
			.append(principal)
			.toHashCode();
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.security.AclEntry#hasPermission(kiff.security.Permission)
	 */
	public boolean hasPermission(final Permission permission) {
		if (this.permission == null) {
			return false;
		}
		return this.permission.check(permission);
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.security.AclEntry#setAcl(kiff.security.Acl)
	 */
	public void setAcl(final Acl acl) {
		this.acl = acl;
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.entity.CoreEntity#setId(java.io.Serializable)
	 */
	public void setId(final Integer id) {
		this.id = id;
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.security.AclEntry#setPermission(kiff.security.Permission)
	 */
	public void setPermission(final Permission permission) {
		this.permission = permission;
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.security.AclEntry#setPrincipal(kiff.security.Principal)
	 */
	public void setPrincipal(final Principal principal) {
		this.principal = principal;
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return new ToStringBuilder(this)
			.append("id", id)
			.append("role", principal)
			.append("permission", permission)
			.toString();
	}
}
